//
// Created by secon on 2025/2/15.
//

#ifndef DAY32_TEMPLATEMETA_LOGGER_H
#define DAY32_TEMPLATEMETA_LOGGER_H

#include <iostream>
#include <string>
#include <type_traits>
//通用模板类
template<typename T, typename Enable = void>
class Logger{
public:
    static void log(const T& value){
        std::cout << "General Logger: " << value << std::endl;
    }
};

//类模板偏特化，当T是指针类型
template<typename T>
class Logger<T, typename std::enable_if<std::is_pointer<T>::value>::type>{
public:
    static void log(T value){
        if(value){
            std::cout << "Pointer Logger: " << *value << std::endl;
        }else{
            std::cout << "Pointer Logger: nullptr" << std::endl;
        }
    }
};

//类模板全特化: 当T是std::string类型
template<>
class Logger<std::string>{
public:
    static void log(const std::string& value){
        std::cout << "String Logger: " << value << std::endl;
    }
};

//函数模板，用于递归调用Logger::log
template<typename T>
void logOne( const T& value){
    Logger<T>::log(value);
}

//使用模板折叠表达式实现可变参数列表打印
template<typename... Args>
void logAll(const Args&... args){
    (logOne(args),...);
}

template<int N>
struct Factorial{
    static const int value = N * Factorial<N-1>::value;
};

template<>
struct Factorial<0>{
    static const int value = 1;
};

template<int N>
const int Factorial<N>::value;

template<int N>
struct Fibonacci{
    inline static const long long value = Fibonacci<N-1>::value + Fibonacci<N-2>::value;
};

template<>
struct Fibonacci<0>{
    inline static const long long value = 0;
};

template<>
struct Fibonacci<1>{
    inline static const long long value = 1;
};

template<typename T, typename = void>
struct is_addable : std::false_type {

};

template<typename T>
struct is_addable<T, decltype(void(std::declval<T>() + std::declval<T>()))>: std::true_type{

};

template<int... Ns>
struct Sum;

template<>
struct Sum<>{
    static const int value = 0;
};

template<int N, int... Ns>
struct Sum<N, Ns...>{
    static const int value = N + Sum<Ns...>::value;
};

//定义类型列表
template<typename... Ts>
struct TypeList{

};

//获取类型列表中第N个类型
template<typename List, std::size_t N>
struct TypeAt;

template<typename Head, typename... Tail>
struct TypeAt<TypeList<Head,Tail...>,0>{
    using type = Head;
};

template<typename Head, typename... Tail, std::size_t N>
struct TypeAt<TypeList<Head, Tail...>, N>{
    using type = typename TypeAt<TypeList<Tail...>, N-1>::type;
};



#endif //DAY32_TEMPLATEMETA_LOGGER_H
